from langchain_core.tools import tool
from typing import Annotated, Optional
from playwright.sync_api import sync_playwright, Page
import base64
import logging
import json

logger = logging.getLogger(__name__)

_browser_sessions = {}

def _execute_action(page: Page, action: dict) -> dict:
    """执行单个浏览器操作"""
    action_type = action.get("action")
    result = {"action": action_type, "success": True}
    
    if action_type == "navigate":
        url = action.get("url")
        if not url:
            return {"success": False, "error": "navigate需要url参数"}
        page.goto(url, wait_until="networkidle", timeout=30000)
        result["title"] = page.title()
        result["url"] = page.url
        
    elif action_type == "click":
        selector = action.get("selector")
        if not selector:
            return {"success": False, "error": "click需要selector参数"}
        page.click(selector)
        page.wait_for_load_state("networkidle", timeout=5000)
        result["message"] = f"已点击: {selector}"
        
    elif action_type == "type":
        selector = action.get("selector")
        text = action.get("text")
        if not selector or text is None:
            return {"success": False, "error": "type需要selector和text参数"}
        page.fill(selector, text)
        result["message"] = f"已输入: {text}"
        
    elif action_type == "wait":
        ms = action.get("ms", 1000)
        page.wait_for_timeout(ms)
        result["message"] = f"等待 {ms}ms"
        
    elif action_type == "content":
        content = page.evaluate("document.body.innerText")
        result["content"] = content[:5000]
        if len(content) > 5000:
            result["note"] = "内容已截断"
            
    elif action_type == "html":
        html = page.content()
        result["html"] = html[:5000]
        if len(html) > 5000:
            result["note"] = "HTML已截断"
            
    elif action_type == "screenshot":
        screenshot_bytes = page.screenshot(full_page=False)
        result["screenshot_base64"] = base64.b64encode(screenshot_bytes).decode('utf-8')
        
    else:
        return {"success": False, "error": f"未知操作: {action_type}"}
    
    return result

@tool
def web_browser(
    url: Annotated[str, "起始URL"],
    actions: Annotated[str, "操作序列JSON字符串，格式: [{\"action\":\"click\",\"selector\":\"#btn\"},{\"action\":\"content\"}]"],
    headless: Annotated[bool, "是否无头模式"] = False
) -> dict:
    """Web浏览器工具，支持多步连续操作。
    
    先访问url，然后按顺序执行actions中的操作。
    
    支持的操作类型:
    - navigate: 跳转到新URL，需要url参数
    - click: 点击元素，需要selector参数
    - type: 输入文本，需要selector和text参数
    - wait: 等待，可选ms参数(默认1000ms)
    - content: 获取页面文本
    - html: 获取页面HTML
    - screenshot: 截图
    
    示例: actions='[{"action":"click","selector":"#search"},{"action":"type","selector":"#input","text":"test"},{"action":"content"}]'
    """
    try:
        actions_list = json.loads(actions)
    except:
        return {"success": False, "error": "actions必须是有效的JSON数组"}
    
    try:
        with sync_playwright() as p:
            browser = p.chromium.launch(
                headless=headless,
                args=[
                    '--disable-blink-features=AutomationControlled',
                    '--disable-dev-shm-usage',
                    '--no-sandbox'
                ]
            )
            context = browser.new_context(
                viewport={'width': 1280, 'height': 800},
                user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            )
            
            context.add_init_script("""
                Object.defineProperty(navigator, 'webdriver', {
                    get: () => undefined
                });
                Object.defineProperty(navigator, 'plugins', {
                    get: () => [1, 2, 3, 4, 5]
                });
                Object.defineProperty(navigator, 'languages', {
                    get: () => ['zh-CN', 'zh', 'en']
                });
                window.chrome = {
                    runtime: {}
                };
            """)
            
            page = context.new_page()
            
            page.goto(url, wait_until="networkidle", timeout=30000)
            
            results = [{
                "action": "navigate",
                "success": True,
                "title": page.title(),
                "url": page.url
            }]
            
            for action in actions_list:
                try:
                    result = _execute_action(page, action)
                    results.append(result)
                    if not result.get("success"):
                        break
                except Exception as e:
                    results.append({
                        "action": action.get("action"),
                        "success": False,
                        "error": str(e)
                    })
                    break
            
            browser.close()
            return {"success": True, "results": results}
            
    except Exception as e:
        logger.error(f"[web_browser] 执行失败: {e}")
        error_msg = str(e)
        if "Executable doesn't exist" in error_msg:
            error_msg += " (请运行 'playwright install')"
        return {"success": False, "error": error_msg}

WebBrowserTool = [web_browser]
